<html>
<head>
<title>How to write a class object for a C++ class</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="highlight.css" type="text/css">
</head>

<body bgcolor="#FFFFFF" text="#000000">
<p><font size="6"><i><b>How to write a class object for a C++ class</b></i></font></p>
<p><font size="4">This topic is fundamental in the understanding of how the class 
  object and the object hierarchy framework interact with each other. Let's say 
  we have a simple class:</font></p>
<pre>
<span class="key">class </span>Simple
{
<span class="key">public</span>:
  Simple();
  <span class="key">virtual </span>~Simple();
  
  <span class="typ">void </span>DoSomething();
  <span class="typ">void </span>PrintString(<span class="typ">const </span>std::string&amp; s);
  <span class="typ">void </span>PrintInt(<span class="typ">int </span>i);
  <span class="typ">void </span>PrintFloat(<span class="typ">float </span>f);
  <span class="typ">void </span>PrintBool(<span class="typ">bool </span>b);
};
</pre>
<p><font size="4">Now, in order to write a class object for this class we must 
  do two things. First, the class must derive from the zeitgeist::Object class 
  (or one of its descendants, especially Leaf and Node if instances of this class 
  are to live in the object hierarchy). In addition to this, a class object must 
  be declared and defined, which serves as a factory for instances of this class.</font></p>
<p><font size="4">The first step is performed easily:</font></p>
<pre><span class="dir">#include &lt;zeitgeist/leaf.h&gt;
</span>
<span class="key">class </span>Simple : <span class="key">public </span>zeitgeist::Leaf
{
<span class="key">public</span>:
  Simple();
  <span class="key">virtual </span>~Simple();
  
  <span class="typ">void </span>DoSomething();
  <span class="typ">void </span>PrintString(<span class="typ">const </span>std::string&amp; s);
  <span class="typ">void </span>PrintInt(<span class="typ">int </span>i);
  <span class="typ">void </span>PrintFloat(<span class="typ">float </span>f);
  <span class="typ">void </span>PrintBool(<span class="typ">bool </span>b);
};
</pre>
<p><font size="4">Now, we just have to write a class object for this class. As 
  this is a pretty repetitive procedure, several helper-macros exist to make this 
  as painless as possible. First, we declare the class object. This is done in 
  the header file with the DECLARE_CLASS()-macro:</font></p>
<pre><span class="dir">#include &lt;zeitgeist/leaf.h&gt;
</span>
<span class="key">class </span>Simple : <span class="key">public </span>zeitgeist::Leaf
{
<span class="key">public</span>:
  Simple();
  <span class="key">virtual </span>~Simple();
  
  <span class="typ">void </span>DoSomething();
  <span class="typ">void </span>PrintString(<span class="typ">const </span>std::string&amp; s);
  <span class="typ">void </span>PrintInt(<span class="typ">int </span>i);
  <span class="typ">void </span>PrintFloat(<span class="typ">float </span>f);
  <span class="typ">void </span>PrintBool(<span class="typ">bool </span>b);
};

DECLARE_CLASS(Simple);
</pre>
<p><font size="4">With this macro, we declare the class object. If Simple would 
  have been an abstract base class (containing one or more pure virtual functions) 
  we would have needed to use the DECLARE_ABSTRACTCLASS()-macro instead. What 
  do these macros actually do. Both create a new class with the mangled name Class_XXXX, 
  where XXXX is the name of the class. In our case this would be Class_Simple. 
  This class is derived from zeitgeist::Class. In the case of DECLARE_CLASS() 
  the macro also provides a CreateInstance() function, which creates an instance 
  of the Simple class (upcast to zeitgeist::Object). DECLARE_ABSTRACTCLASS() does 
  not do this, as it is impossible to create an instance of an abstract class. 
  It inherits the base behavior from zeitgeist::Class, which just returns NULL. 
  In addition to this, both macros declare a DefineClass() member function, which 
  needs to be implemented to define the class object fully. This is done in an 
  additional CPP file. If the class above was implemented in the files simple.h 
  and simple.cpp, the accompanying class object should be placed in the file simple_c.cpp. 
  This naming convention has been found useful during development and should be 
  adopted. A minimal simple_c.cpp should look like this:</font></p>
<pre><span class="dir">#include </span><span class="dstr">&quot;simple.h&quot;</span><span class="dir"></span>

<span class="key">using namespace </span>zeitgeist;

<span class="typ">void </span>CLASS(Simple)::DefineClass()
{
  DEFINE_BASECLASS(zeitgeist/Leaf);
}
</pre>
<p><font size="4">The CLASS()-macro is used to identify the name of the class 
  object. In the above example, it just resolves to Class_Simple. DEFINE_BASECLASS() 
  is used to identify the base class of the class described by this class object. 
  This can appear multiple times to allow for multiple inheritance. We now have 
  a working class object. The problem is, that the object hierarchy does not know 
  this class object, yet. So, we can't really use it. The <a href="class_register.html">next 
  HowTo</a> explains how to register these class objects.</font></p>
</body>
</html>

